/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
 * (c) 2001 - 2013 OpenPlans
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.wicket.test;

import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WicketServlet;
import org.apache.wicket.resource.Properties;
import org.apache.wicket.resource.PropertiesFactory;
import org.apache.wicket.resource.loader.ClassStringResourceLoader;
import org.apache.wicket.resource.loader.ComponentStringResourceLoader;
import org.apache.wicket.settings.ResourceSettings;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.GeoServerResourceStreamLocator;
import org.geoserver.web.GeoServerStringResourceLoader;

/** Application object for your web application. */
public class WicketTestApplication extends WebApplication {
    /** Constructor */
    public WicketTestApplication() {}

    static String wtapath =
            WicketTestApplication.class.getPackage().getName().replaceAll("\\.", "/");
    static String gsapath =
            GeoServerApplication.class.getPackage().getName().replaceAll("\\.", "/");

    static {
        wtapath += "/" + WicketTestApplication.class.getSimpleName();
        gsapath += "/" + GeoServerApplication.class.getSimpleName();
    }

    @Override
    protected void init() {
        // JD: override some resource settings to allow for custom i18n lookups
        getResourceSettings().setResourceStreamLocator(new GeoServerResourceStreamLocator());

        getResourceSettings().getStringResourceLoaders().add(new GeoServerStringResourceLoader());
        getResourceSettings().getStringResourceLoaders().add(new ComponentStringResourceLoader());
        getResourceSettings()
                .getStringResourceLoaders()
                .add(new ClassStringResourceLoader(this.getClass()));

        getResourceSettings()
                .setPropertiesFactory(
                        new PropertiesFactory(new ResourceSettings(this)) {
                            @Override
                            public Properties load(Class<?> clazz, String path) {
                                if (clazz == WicketTestApplication.class
                                        && path.startsWith(wtapath)) {
                                    String newPath = path.replace(wtapath, gsapath);
                                    return super.load(GeoServerApplication.class, newPath);
                                }
                                return super.load(clazz, path);
                            }
                        });
    }

    /** @see wicket.Application#getHomePage() */
    public Class<? extends Page> getHomePage() {
        return TestHomePage.class;
    }

    /**
     * Starts a Wicket tester application that will allow for quick interactive testing of the
     * {@link Component} generated by the factory (may be a {@link Page}, in that case the home page
     * will redirect to it).
     *
     * <p>The application will be hosted on path "/", port 8080
     */
    public static void start(IComponentFactory factory) {
        start(factory, "/", 8080);
    }

    /**
     * Same as {@link #start(IComponentFactory)}, but allows to specify the context path and the
     * port
     */
    public static void start(IComponentFactory factory, String contextPath, int port) {
        // sanity check and install the factory
        if (factory == null) {
            throw new NullPointerException("You must provide a non null component factory");
        }
        TestHomePage.componentFactory = factory;

        // setup the embedded Jetty server
        Server server = new Server();
        ServerConnector connector = new ServerConnector(server);

        // Set some timeout options to make debugging easier.
        connector.setIdleTimeout(1000 * 60 * 60);
        connector.setPort(port);
        server.setConnectors(new Connector[] {connector});

        // programmatically add the wicket servlet to the context
        ServletContextHandler root =
                new ServletContextHandler(server, contextPath, WebAppContext.SESSIONS);
        ServletHolder wicket = new ServletHolder(WicketServlet.class);
        wicket.setInitParameter("applicationClassName", WicketTestApplication.class.getName());
        root.addServlet(wicket, "/*");

        try {
            System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
            server.start();
            while (System.in.available() == 0) {
                Thread.sleep(1000);
            }
            server.stop();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(100);
        }
    }
}
